﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DevExpress.XtraEditors;
using System.Data;
using System.ComponentModel;
using ProgNetComponentsDx.Browsers;
using DevExpress.XtraGrid.Columns;
using ProgNetComponentsDx.Controls.Editors.Design;
using System.Drawing.Design;
using DevExpress.XtraEditors.Registrator;
using DevExpress.XtraEditors.Drawing;
using System.Drawing;
using DevExpress.Accessibility;

namespace ProgNetComponentsDx.Controls.Editors
{
    public class MultiSelectGridEditPopup : PopupContainerControl
    {
        internal DevExpress.XtraGrid.GridControl gcMain;
        internal DevExpress.XtraGrid.Views.Grid.GridView gvMain;
        internal DevExpress.XtraGrid.Columns.GridColumn colSelect;
        private DevExpress.XtraEditors.Repository.RepositoryItemCheckEdit repItemSelect;

        private List<object> selectedObjects = new List<object>();
        private BrowserProvider browserProvider1;
        private IContainer components;

        public List<object> SelectedObjects
        {
            get { return selectedObjects; }
        }
        private List<object> deletedObjects = new List<object>();
        public List<object> DeletedObjects
        {
            get { return deletedObjects; }
        }
        public MultiSelectGridEditPopup()
        {
            InitializeComponent();
        }
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.gcMain = new DevExpress.XtraGrid.GridControl();
            this.gvMain = new DevExpress.XtraGrid.Views.Grid.GridView();
            this.colSelect = new DevExpress.XtraGrid.Columns.GridColumn();
            this.repItemSelect = new DevExpress.XtraEditors.Repository.RepositoryItemCheckEdit();
            this.browserProvider1 = new ProgNetComponentsDx.Browsers.BrowserProvider(this.components);
            ((System.ComponentModel.ISupportInitialize)(this.gcMain)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.gvMain)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.repItemSelect)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.browserProvider1)).BeginInit();
            this.SuspendLayout();
            // 
            // gcMain
            // 
            this.gcMain.Dock = System.Windows.Forms.DockStyle.Fill;
            this.gcMain.Location = new System.Drawing.Point(0, 0);
            this.gcMain.MainView = this.gvMain;
            this.gcMain.Name = "gcMain";
            this.gcMain.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] {
            this.repItemSelect});
            this.gcMain.Size = new System.Drawing.Size(335, 231);
            this.gcMain.TabIndex = 0;
            this.gcMain.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] {
            this.gvMain});
            // 
            // gvMain
            // 
            this.gvMain.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] {
            this.colSelect});
            this.gvMain.GridControl = this.gcMain;
            this.gvMain.Name = "gvMain";
            this.gvMain.OptionsView.ShowFilterPanelMode = DevExpress.XtraGrid.Views.Base.ShowFilterPanelMode.Never;
            this.gvMain.OptionsView.ShowGroupPanel = false;
            this.gvMain.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gvMain_RowClick);
            this.gvMain.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gvMain_CustomUnboundColumnData);
            // 
            // colSelect
            // 
            this.colSelect.Caption = " ";
            this.colSelect.ColumnEdit = this.repItemSelect;
            this.colSelect.FieldName = "colSelect";
            this.colSelect.Fixed = DevExpress.XtraGrid.Columns.FixedStyle.Left;
            this.colSelect.MaxWidth = 25;
            this.colSelect.MinWidth = 25;
            this.colSelect.Name = "colSelect";
            this.colSelect.OptionsColumn.AllowMove = false;
            this.colSelect.OptionsColumn.AllowShowHide = false;
            this.colSelect.OptionsColumn.AllowSize = false;
            this.colSelect.OptionsColumn.ShowCaption = false;
            this.colSelect.OptionsColumn.ShowInCustomizationForm = false;
            this.colSelect.UnboundType = DevExpress.Data.UnboundColumnType.Boolean;
            this.colSelect.Visible = true;
            this.colSelect.VisibleIndex = 0;
            this.colSelect.Width = 25;
            // 
            // repItemSelect
            // 
            this.repItemSelect.AutoHeight = false;
            this.repItemSelect.Name = "repItemSelect";
            // 
            // MultiSelectGridEditPopup
            // 
            this.Controls.Add(this.gcMain);
            this.Name = "MultiSelectGridEditPopup";
            this.Size = new System.Drawing.Size(335, 231);
            ((System.ComponentModel.ISupportInitialize)(this.gcMain)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.gvMain)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.repItemSelect)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.browserProvider1)).EndInit();
            this.ResumeLayout(false);

        }

        /// <summary>
        /// Gets or sets table for all records displayed in grid
        /// </summary>
        public object DataSource
        {
            get { return gcMain.DataSource; }
            set { gcMain.DataSource = value; }
        }
        private DataTable DataSourceAsTable
        {
            get
            {
                if (DataSource is DataTable)
                    return DataSource as DataTable;
                if (DataSource is DataView)
                    return (DataSource as DataView).Table;
                return null;
            }
        }
        /// <summary>
        /// Gets or sets table that will contain only selected records
        /// </summary>
        public DataTable ResultTable
        {
            get;
            set;
        }
        public string ResultTableKeyColumn
        {
            get;
            set;
        }
        public string ResultTableLinkColumn
        {
            get;
            set;
        }
        public string ValueMember
        {
            get;
            set;
        }
        public string DisplayMember
        {
            get;
            set;
        }
        public string Separator
        {
            get;
            set;
        }
        public bool MarkOnRowClick
        {
            get;
            set;
        }
        private void gvMain_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e)
        {
            if (e.Column == colSelect)
            {
                DataTable dt = gvMain.GetDataTable();
                if (dt != null)
                {
                    if (dt.Rows.Count < e.ListSourceRowIndex)
                        return;

                    DataRow row = dt.Rows[e.ListSourceRowIndex];
                    if (row != null)
                    {
                        object obj = row[ValueMember];
                        if (obj != null)
                        {
                            if (e.IsGetData)
                            {
                                e.Value = selectedObjects.Contains(obj);
                            }
                            else if (e.IsSetData)
                            {
                                if (e.Value.AsBool())
                                {
                                    selectedObjects.AddIfNotExist(obj);
                                    deletedObjects.Remove(obj);
                                }
                                else
                                {
                                    deletedObjects.AddIfNotExist(obj);
                                    selectedObjects.Remove(obj);
                                }
                            }
                        }
                    }
                }
            }
        }

        public void SetSelection(object key)
        {
            if (DataSourceAsTable == null || ResultTable == null)
                return;
            string filter = "";
            if (key.IsNull())
            {
                filter = ResultTableKeyColumn + " IS NULL";
                if (DataSourceAsTable.Columns[ResultTableKeyColumn].DataType == typeof(string))
                    filter += " OR " + ResultTableKeyColumn + " = ''";
            }
            else
            {
                filter = ResultTableKeyColumn + " = " + key.AsString().EscapeSql();
            }
            try
            {
                DataRow[] rows = ResultTable.Select(filter);
                selectedObjects.Clear();
                foreach (DataRow r in rows)
                {
                    selectedObjects.AddIfNotExist(r[ResultTableLinkColumn]);
                }
            }
            catch (Exception ex)
            {
                ex.LogInternal();
            }
            gcMain.RefreshDataSource();
        }
        public string GetDisplayedText(object key)
        {
            if (DataSourceAsTable == null || ResultTable == null)
                return string.Empty;
            string str = "";
            string filter = "";
            if (key.IsNull())
            {
                filter = ResultTableKeyColumn + " IS NULL";
                if (ResultTable.Columns[ResultTableKeyColumn].DataType == typeof(string))
                    filter += " OR " + ResultTableKeyColumn + " = ''";
            }
            else
            {
                filter = ResultTableKeyColumn + " = " + key.AsString().EscapeSql();
            }
            try
            {
                DataRow[] rows = ResultTable.Select(filter);
                object val;
                DataRow sourceRow;
                foreach (DataRow r in rows)
                {
                    val = r[ResultTableLinkColumn];
                    sourceRow = DataSourceAsTable.SelectFirstRow(ValueMember + " = " + val.AsString().EscapeSql());
                    if (sourceRow != null)
                    {
                        str = str.AppendString(Separator);
                        str += sourceRow[DisplayMember].AsString();
                    }
                }
            }
            catch (Exception ex)
            {
                ex.LogInternal();
            }
            return str;
        }

        private void gvMain_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e)
        {
            if (MarkOnRowClick)
            {
                gvMain.SetRowCellValue(e.RowHandle, colSelect, !gvMain.GetRowCellValue(e.RowHandle, colSelect).AsBool());
            }
        }

        public void PopulateColumns(Browser browser = null)
        {
            gvMain.Columns.Clear();
            gcMain.RepositoryItems.Clear();

            if (browser != null)
            {
                GridColumn cl;
                foreach (BrowserColumn c in browser.Columns)
                {
                    cl = BrowserTools.CreateColumn(c, gvMain, browserProvider1);
                    cl.OptionsColumn.AllowEdit = false;
                    cl.OptionsColumn.AllowMove = false;
                    cl.OptionsColumn.AllowShowHide = false;
                    cl.OptionsColumn.ReadOnly = true;
                    cl.OptionsFilter.AllowFilter = false;
                    if (!gvMain.Columns.Contains(cl))
                        gvMain.Columns.Add(cl);
                }
            }
            else
            {
                gvMain.PopulateColumns();
            }
            gcMain.RepositoryItems.Add(repItemSelect);
            gvMain.Columns.Insert(0, colSelect);
            colSelect.Visible = true;
            colSelect.VisibleIndex = 0;
        }
        public bool ShouldPopulateColumns()
        {
            return gvMain.Columns.Count == 0 || (gvMain.Columns.Count == 1 && gvMain.Columns[0] == colSelect);
        }

        internal void HideAllColumns()
        {
            foreach (GridColumn c in gvMain.Columns)
                c.Visible = false;
            colSelect.Visible = true;
            colSelect.VisibleIndex = 0;
        }

        internal void ShowColumn(string column)
        {
            GridColumn c = gvMain.Columns[column];
            if (c != null)
                c.Visible = true;
            colSelect.Visible = true;
            colSelect.VisibleIndex = 0;
        }

        internal void CloseEditor()
        {
            gvMain.CloseEditor();
        }
        public GridColumnCollection Columns
        {
            get { return gvMain.Columns; }
        }
    }

    public class MultiSelectGridEdit : DevExpress.XtraEditors.PopupContainerEdit
    {
        public MultiSelectGridEdit()
        {

        }
        protected override void CreateRepositoryItem()
        {
            fProperties = new RepositoryItemMultiSelectGridEdit(this);
        }

        public new RepositoryItemMultiSelectGridEdit Properties
        {
            get { return fProperties as RepositoryItemMultiSelectGridEdit; }
        }
        
    }

    [UserRepositoryItem("Register")]
    public class RepositoryItemMultiSelectGridEdit : DevExpress.XtraEditors.Repository.RepositoryItemPopupContainerEdit
    {
        static RepositoryItemMultiSelectGridEdit()
        {
            Register();
        }
        public static void Register()
        {
            if (!EditorRegistrationInfo.Default.Editors.Contains("MultiSelectGridEdit"))
                EditorRegistrationInfo.Default.Editors.Add(
                    new EditorClassInfo("MultiSelectGridEdit", 
                        typeof(MultiSelectGridEdit),
                        typeof(RepositoryItemMultiSelectGridEdit), 
                        typeof(DevExpress.XtraEditors.ViewInfo.ButtonEditViewInfo), 
                        (BaseEditPainter)new ButtonEditPainter(), true, (Image)null, 
                        typeof(PopupEditAccessible)));
        }

        private MultiSelectGridEditPopup popup;
        private void Init()
        {
            popup = new MultiSelectGridEditPopup();
            Separator = ", ";
            PopupControl = popup;
            this.QueryDisplayText += new DevExpress.XtraEditors.Controls.QueryDisplayTextEventHandler(RepositoryItemMultiSelectGridEdit_QueryDisplayText);
            this.Popup += new EventHandler(RepositoryItemMultiSelectGridEdit_Popup);
            this.Closed += new DevExpress.XtraEditors.Controls.ClosedEventHandler(RepositoryItemMultiSelectGridEdit_Closed);
        }

        void RepositoryItemMultiSelectGridEdit_Closed(object sender, DevExpress.XtraEditors.Controls.ClosedEventArgs e)
        {
            if (e.CloseMode != PopupCloseMode.Cancel)
            {
                BaseEdit edit = sender as BaseEdit;
                if (edit != null)
                {
                    DataRow row;
                    string filter = "";
                    object key = edit.EditValue;
                    if (key.IsNotNull())
                    {
                        filter = ResultTableKeyColumn + " = " + key.AsString().EscapeSql();
                        try
                        {
                            popup.CloseEditor();
                            DataRow[] rows = ResultTable.Select(filter);
                            object item;
                            CancelDataRowEventArgs ea;
                            foreach (DataRow r in rows)
                            {
                                DataRowEventArgs rEa = new DataRowEventArgs(r);
                                item = r[ResultTableLinkColumn];
                                if (popup.DeletedObjects.Contains(item))
                                {
                                    ea = new CancelDataRowEventArgs(r);
                                    OnRowDeleting(sender, ea);
                                    if (!ea.Cancel)
                                    {
                                        r.Delete();
                                        OnRowDeleted(sender, rEa);
                                        OnRowModified(sender, rEa);
                                    }
                                }
                                if (popup.SelectedObjects.Contains(item))
                                {
                                    popup.SelectedObjects.Remove(item);
                                }
                            }
                            foreach (object o in popup.SelectedObjects)
                            {
                                row = ResultTable.NewRow();
                                row[ResultTableKeyColumn] = key;
                                row[ResultTableLinkColumn] = o;
                                ea = new CancelDataRowEventArgs(row);
                                OnRowAdding(sender, ea);
                                if (!ea.Cancel)
                                {
                                    DataRowEventArgs rEa = new DataRowEventArgs(row);
                                    ResultTable.Rows.Add(row);
                                    OnRowAdded(sender, rEa);
                                    OnRowModified(sender, rEa);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            ex.LogInternal();
                        }
                    }
                }
            }
        }

        void RepositoryItemMultiSelectGridEdit_Popup(object sender, EventArgs e)
        {
            if (popup.ShouldPopulateColumns())
                popup.PopulateColumns();
            BaseEdit edit = sender as BaseEdit;
            if (edit != null)
                popup.SetSelection(edit.EditValue);
        }

        public RepositoryItemMultiSelectGridEdit()
        {
            Init();
        }

        public RepositoryItemMultiSelectGridEdit(MultiSelectGridEdit multiSelectGridEdit)
        {
            Init();
            SetOwnerEdit(multiSelectGridEdit);
        }

        void RepositoryItemMultiSelectGridEdit_QueryDisplayText(object sender, DevExpress.XtraEditors.Controls.QueryDisplayTextEventArgs e)
        {
            e.DisplayText = popup.GetDisplayedText(e.EditValue);
        }

        public override DevExpress.XtraEditors.BaseEdit CreateEditor()
        {
            return new MultiSelectGridEdit();
        }

        public override void Assign(DevExpress.XtraEditors.Repository.RepositoryItem item)
        {
            base.Assign(item);
            RepositoryItemMultiSelectGridEdit other = item as RepositoryItemMultiSelectGridEdit;
            if (other != null)
            {
                this.DataSource = other.DataSource;
                this.DisplayMember = other.DisplayMember;
                this.ValueMember= other.ValueMember;

                this.ResultTable = other.ResultTable;
                this.ResultTableKeyColumn = other.ResultTableKeyColumn;
                this.ResultTableLinkColumn = other.ResultTableLinkColumn;
                this.Separator = other.Separator;
                this.MarkOnRowClick = other.MarkOnRowClick;

                if (this.popup != other.popup)
                {
                    if (this.popup != null)
                        this.popup.Dispose();
                    this.popup = other.popup;
                }

                this.Events.AddHandler(RepositoryItemMultiSelectGridEdit.RowAddedObj, other.Events[RepositoryItemMultiSelectGridEdit.RowAddedObj]);
                this.Events.AddHandler(RepositoryItemMultiSelectGridEdit.RowAddingObj, other.Events[RepositoryItemMultiSelectGridEdit.RowAddingObj]);
                this.Events.AddHandler(RepositoryItemMultiSelectGridEdit.RowDeletedObj, other.Events[RepositoryItemMultiSelectGridEdit.RowDeletedObj]);
                this.Events.AddHandler(RepositoryItemMultiSelectGridEdit.RowDeletingObj, other.Events[RepositoryItemMultiSelectGridEdit.RowDeletingObj]);
                this.Events.AddHandler(RepositoryItemMultiSelectGridEdit.RowModifiedObj, other.Events[RepositoryItemMultiSelectGridEdit.RowModifiedObj]);
            }
        }

        #region Properties
        public override DevExpress.XtraEditors.Controls.TextEditStyles TextEditStyle
        {
            get
            {
                return DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor;
            }
            set
            {

            }
        }

        public DataTable DataSourceAsTable
        {
            get
            {
                if (DataSource is DataTable)
                    return DataSource as DataTable;
                if (DataSource is DataView)
                    return (DataSource as DataView).Table;
                return null;
            }
        }
        /// <summary>
        /// Gets datasource for the view (all records)
        /// </summary>
        [Category(ProgNetComponents.Constants.Categories.ProgNetData)]
        [AttributeProvider(typeof(IListSource))]
        public object DataSource
        {
            get { return popup.DataSource; }
            set { popup.DataSource = value; }
        }

        /// <summary>
        /// Gets or sets key column for DataSource table
        /// </summary>
        [Category(ProgNetComponents.Constants.Categories.ProgNetData)]
        [Editor(typeof(MultiSelectEditDataSourceColumnEditor), typeof(UITypeEditor))]
        public string ValueMember
        {
            get { return popup.ValueMember; }
            set { popup.ValueMember = value; }
        }

        /// <summary>
        /// Gets or sets column whitch will be used for displaying text
        /// </summary>
        [Category(ProgNetComponents.Constants.Categories.ProgNetData)]
        [Editor(typeof(MultiSelectEditDataSourceColumnEditor), typeof(UITypeEditor))]
        public string DisplayMember
        {
            get { return popup.DisplayMember; }
            set { popup.DisplayMember = value; }
        }

        /// <summary>
        /// Gets or sets separator used to display many values
        /// </summary>
        [DefaultValue(", ")]
        [Category(ProgNetComponents.Constants.Categories.ProgNetDisplay)]
        public string Separator
        {
            get { return popup.Separator; }
            set { popup.Separator = value; }
        }

        /// <summary>
        /// Gets or sets result table (table with only selected records)
        /// </summary>
        [Category(ProgNetComponents.Constants.Categories.ProgNetData)]
        public DataTable ResultTable
        {
            get { return popup.ResultTable; }
            set { popup.ResultTable = value; }
        }

        /// <summary>
        /// Gets or sets column from Result table whits is the key column
        /// </summary>
        [Category(ProgNetComponents.Constants.Categories.ProgNetData)]
        [Editor(typeof(MultiSelectEditResultColumnEditor), typeof(UITypeEditor))]
        public string ResultTableKeyColumn
        {
            get { return popup.ResultTableKeyColumn; }
            set { popup.ResultTableKeyColumn = value; }
        }

        /// <summary>
        /// Gets or sets column from result table whitch is reference to ValueMember
        /// </summary>
        [Category(ProgNetComponents.Constants.Categories.ProgNetData)]
        [Editor(typeof(MultiSelectEditResultColumnEditor), typeof(UITypeEditor))]
        public string ResultTableLinkColumn
        {
            get { return popup.ResultTableLinkColumn; }
            set { popup.ResultTableLinkColumn = value; }
        }

        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool MarkOnRowClick
        {
            get { return popup.MarkOnRowClick; }
            set { popup.MarkOnRowClick = value; }
        }

        [Category(ProgNetComponents.Constants.Categories.ProgNetDisplay)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public GridColumnCollection Columns
        {
            get { return popup.Columns; }
        }
        #endregion

        static object RowDeletingObj = new object();
        static object RowAddingObj = new object();
        static object RowDeletedObj = new object();
        static object RowAddedObj = new object();
        static object RowModifiedObj = new object();

        #region Events
        /// <summary>
        /// Event fires when row is about to be deleted
        /// </summary>
        public event CancelDataRowHandler RowDeleting
        {
            add { Events.AddHandler(RowDeletingObj, value); }
            remove { Events.RemoveHandler(RowDeletingObj, value); }
        }
        /// <summary>
        /// Event fires when row is about to be added
        /// </summary>
        public event CancelDataRowHandler RowAdding
        {
            add { Events.AddHandler(RowAddingObj, value); }
            remove { Events.RemoveHandler(RowAddingObj, value); }
        }

        /// <summary>
        /// Event fires after row is deleted
        /// </summary>
        public event DataRowHandler RowDeleted
        {
            add { Events.AddHandler(RowDeletedObj, value); }
            remove { Events.RemoveHandler(RowDeletedObj, value); }
        }

        /// <summary>
        /// Event fires after row is added
        /// </summary>
        public event DataRowHandler RowAdded
        {
            add { Events.AddHandler(RowAddedObj, value); }
            remove { Events.RemoveHandler(RowAddedObj, value); }
        }

        /// <summary>
        /// Event fires after row is deleted or added. You can find out operation by Row.RowState.
        /// </summary>
        public event DataRowHandler RowModified
        {
            add { Events.AddHandler(RowModifiedObj, value); }
            remove { Events.RemoveHandler(RowModifiedObj, value); }
        }

        #region Event Impl
        protected virtual void OnRowDeleting(object sender, CancelDataRowEventArgs e)
        {
            CancelDataRowHandler h = (CancelDataRowHandler)this.Events[RepositoryItemMultiSelectGridEdit.RowDeletingObj];
            if (h != null)
                h(sender, e);
        }
        protected virtual void OnRowAdding(object sender, CancelDataRowEventArgs e)
        {
            CancelDataRowHandler h = (CancelDataRowHandler)this.Events[RepositoryItemMultiSelectGridEdit.RowAddingObj];
            if (h != null)
                h(sender, e);
        }

        protected virtual void OnRowDeleted(object sender, DataRowEventArgs e)
        {
            DataRowHandler h = (DataRowHandler)this.Events[RepositoryItemMultiSelectGridEdit.RowDeletedObj];
            if (h != null)
                h(sender, e);
        }
        protected virtual void OnRowAdded(object sender, DataRowEventArgs e)
        {
            DataRowHandler h = (DataRowHandler)this.Events[RepositoryItemMultiSelectGridEdit.RowAddedObj];
            if (h != null)
                h(sender, e);
        }
        protected virtual void OnRowModified(object sender, DataRowEventArgs e)
        {
            DataRowHandler h = (DataRowHandler)this.Events[RepositoryItemMultiSelectGridEdit.RowModifiedObj];
            if (h != null)
                h(sender, e);
        }
        #endregion
        #endregion

        public void PopulateColumns(Browser browser = null)
        {
            popup.PopulateColumns(browser);
        }
        public void HideAllColumns()
        {
            popup.HideAllColumns();
        }
        public void ShowColumn(string column)
        {
            popup.ShowColumn(column);
        }
    }

    public class CancelDataRowEventArgs : CancelEventArgs
    {
        public DataRow Row
        {
            get;
            private set;
        }

        public CancelDataRowEventArgs(DataRow row)
        {
            Row = row;
        }
    }

    public delegate void CancelDataRowHandler(object sender, CancelDataRowEventArgs e);

    public class DataRowEventArgs : EventArgs
    {
        public DataRow Row
        {
            get;
            private set;
        }

        public DataRowEventArgs(DataRow row)
        {
            Row = row;
        }
    }
    public delegate void DataRowHandler(object sender, DataRowEventArgs e);
}
